Passed
Push — master ( 55414e...5f39f4 )
by Björn
03:25
created

T_VAR ➔ findPath   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
nc 5
crap 30
nop 2
1
/**
2
 * Parses for pattern's documentation
3
 * 
4
 * 
5
 * @package Patternlibrary
6
 */
7 1
var async       = require('async');
8 1
var extend      = require('util')._extend;
9 1
var format      = require('string-template');
10 1
var fm          = require('front-matter');
11 1
var fs          = require('fs');
12 1
var glob        = require('glob');
13 1
var globAll     = require('glob-all');
14 1
var path        = require('path');
15 1
var chalk       = require('chalk');
16 1
var extend      = require('extend');
17 1
var sanatizeType = require('../util/sanatize-patterntype');
18
19 1
module.exports = function(file, opts, cb) {
20
    var _this = this; // this => Supercollider ref, this.$PL => Patternlibrary ref
21
    var page = {};
22
    var pageData = fm(file.contents.toString());
23
    var relativePatternPath = path.relative( this.options.partials,  path.dirname(file.path) );
24
    
25 2
    if (typeof(opts) === 'function') {
26
        cb = opts;
27
        opts = {};
28
    }
29
    // Global attributes
30
    page = pageData.attributes;
31
    //page.__fm = pageData.attributes;
32
    page.docs = '';
33
    page.fileName = path.relative(process.cwd(), file.path);
34
    page._adapterData = {};
35
    page._adapterFiles = {};
36
    page.relatedFiles = [];
37
38
    // Catch Markdown errors
39 2
    if (this.markdown) {
40
        try {
41
            page.docs = this.markdown.render(pageData.body);
42
        }
43
        catch (e) {
44
            throw new Error('Markdown error: ' + e.message);
45
        }
46
    }
47
    else {
48
        page.docs = pageData.body;
49
    }
50
51
    // check for other (mandatory) page.{doctype} 
52 2
    if (!page.source)    { 
53
    	page.source = path.join(relativePatternPath, './index.html');
54
    } else {
55
    	page.source = path.join(relativePatternPath, page.source);
56
    }
57 2
    if (!page.sourcecode) { page.sourcecode = page.source; }
58 2
    if (!page.example)    { page.example    = page.source; }
59 2
    if (!page.specs)      { page.specs      = page.source; }
60 2
    if (!page.changelog)  { page.changelog  = path.join(  relativePatternPath, './changelog.md'); }
61 2
    if (!page.tests)      { page.tests      = path.join(  relativePatternPath, './test.js'); }
62 2
    if (!page.gitinfo)    { page.gitinfo    = path.join(  relativePatternPath, ''); }
63
64
    // Run each adapter's parser, if the page references it
65
    var parseTasks = {};
66
    for (var lib in this.adapters) {
67 2
        if (page[lib]) {
68
        
69
            // Placed inside an IIFE so the value of lib is correct for each function call
70
            (function(lib) {
71
                var collider = {
72
                    "options"  : _this.options,
73
                    "filePath" : path.dirname(page.fileName), //path.relative( _this.$PL.Config.get('partials'),  path.dirname(file.path) ),
74
                    "pattern"  : pageData.title
75
                };
76
          
77
                parseTasks[lib] = function(cb) {
78
                    // Store the original value of the YML property so it can be accessed later if needed
79
                    page._adapterData[lib] = page[lib];
80
  
81
                    // find correct path for 'page[lib]'...
82
                    var adapterFiles = findPath( page[lib], collider );
83
                    page._adapterFiles[lib] = adapterFiles;
84
                    
85
                    // Then find the configuration for the adapter...
86 2
                    var config = extend(_this.adapters[lib].config, _this.options.adapters[lib] || {
87
                        
88
                    });
89
90
                    // ... and run it
91
                    _this.adapters[lib](adapterFiles, config, cb, _this);
92
                };
93
        
94
                parseTasks[lib + '-files'] = function(cb) {
95
                    addFiles(page.relatedFiles, page._adapterFiles[lib], function(files) {
96
                        page.relatedFiles = files;
97
                        cb();
98
                    });
99
                };
100
        
101
            })(lib);
102
      
103
        }
104
    } // for(adapters)
105
106
    async.parallel(parseTasks, function(err, results) {
107
        for (var i in results) {
108
            page[i] = results[i];
109
        }
110
111
        var patternname = sanatizeType(path.dirname(page.source));
112
        _this.data.patterns[patternname] = extend(_this.data.patterns[patternname], page);
113
        //_this.updateDataFile();
114
        _this.log.info('parse tasks finished for "'+chalk.green(patternname)+'"');
115
116
        // debug the main data tree: _this.$PL.debug('tree: ', _this.data);
117
        cb(null, page);
118
    });
119
}
120
121
/**
122
 * find array item-key by object-key value in an array of objects
123
 * 
124
 * @param array
125
 * @param key
126
 * @param value
127
 * @returns integer >= 0 on success, -1 on failure
128
 */
129
function findByKey(array, key, value) {
130
    for (var i in array) {
131 4
        if (array[i][key] && array[i][key] === value) {
132
            return i;
133
        }
134
    }
135
    return -1;
136
}
137
138
/**
139
 * find 'correct' path for '(related)File' globs
140
 * 
141
 * @param   fileGlobs  fileGlobs to look for
142
 * @param   collider   config
143
 * @returns fileGlob
144
 */
145
function findPath(fileGlobs, collider) {
146
    
147
    // look in "partials"/"patterns"' filepath for "file"
148 2
    if ( fs.existsSync( path.join(collider.filePath, fileGlobs) ) ) {
149
        return ( path.join(collider.filePath, fileGlobs) );
150
    }
151
    // look in "partials"/"patterns"' filepath for "*/**/file"
152 2
    if ( fs.existsSync( path.join(collider.filePath, "*/**/", fileGlobs) ) ) {
153
        return ( path.join(collider.filePath, "*/**/", fileGlobs) );
154
    }
155
    
156
    // look in "partials"/"patterns" for "type/name/file" --- (fileGlobs != 'index.html') && 
157 2
    if ( fs.existsSync( path.join(collider.options.partials, fileGlobs) ) ) {
158
        return ( path.join(collider.options.partials, fileGlobs) );
159
    }
160
    
161
    // org. file path
162 2
    if (fs.existsSync( fileGlobs ) ) {
163
        return ( fileGlobs );
164
    }
165
    
166
    // if all fail, return given globs
167
    return(fileGlobs)
168
}
169
170
/**
171
 * add related files to task
172
 * 
173
 * @param   files      related files
174
 * @param   fileGlobs  files to look for
175
 * @param   cb         async callback
176
 */
177
function addFiles(files, fileGlobs, cb) {
178
    var searchGlob = fileGlobs;
179
    globAll(searchGlob, function(err, newFiles) {
180
       cb(files.concat(newFiles));
181
    });
182
}
183